import time
from typing import Optional

import requests

import schedule

from config import Config
from email_notify import EmailNotifier


REQUEST_TIMEOUT_SEC: int = 10


def mk_url(cfg: Config):
    return f'{cfg.protocol}://{cfg.address}/my-some-tool'


def mk_headers(ping_content: str) -> dict[str, str]:
    return {
        'key': '',
        'tool-name': 'ping',
        'ping-content': ping_content
    }


g_last_notify_time_sec: int = 0
g_notify_interval_sec: int = 60 * 60


def do_notify(notifier: EmailNotifier, msg: str):
    notifier.send('Server is not accessible', msg)


def notify(notifier: EmailNotifier, msg: str):
    global g_last_notify_time_sec
    global g_notify_interval_sec
    now_sec: int = int(time.time())
    if g_last_notify_time_sec > 0 and now_sec < g_last_notify_time_sec + g_notify_interval_sec:
        return
    do_notify(notifier=notifier, msg=msg)
    g_last_notify_time_sec = now_sec


def detect_once(cfg: Config, notifier: EmailNotifier):
    global g_last_notify_time_sec

    url: str = mk_url(cfg)
    ping_content: str = f'PING AT {int(time.time())}'
    headers: dict[str, str] = mk_headers(ping_content)
    has_error: bool = False
    rsp: Optional[requests.Response] = None
    try:
        rsp = requests.post(url, verify=True, headers=headers, timeout=REQUEST_TIMEOUT_SEC)
    except:
        has_error = True
        notify(notifier=notifier, msg=f'Timeout to [{url}]')

    if rsp.text != ping_content:
        has_error = True
        notify(notifier=notifier, msg=f'Bad content, should be [{ping_content}], but got [{rsp.text}]')

    # 如果发现正常了，则重置上次通知时间，以便当下次发现错误时可以立刻通知
    if not has_error:
        g_last_notify_time_sec = 0


def start(cfg: Config, notifier: EmailNotifier):
    detect_once(cfg, notifier)
    schedule.every(5).seconds.do(detect_once, cfg, notifier)
